package com.xbongbong.workflow.service.strategy.node;

import com.alibaba.fastjson.JSONObject;
import com.xbongbong.paas.config.enums.WorkflowTaskLogStatusEnum;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.ext.OptionalRangeEntity;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.OptionalRangeEnum;
import com.xbongbong.paas.enums.RuleOperationEnum;
import com.xbongbong.paas.exception.WorkflowException;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.pro.formdata.pojo.SaasNeedRedundantAttrPojo;
import com.xbongbong.sys.domain.entity.DepartmentEntity;
import com.xbongbong.sys.domain.entity.UserDepartmentEntity;
import com.xbongbong.sys.help.SysUserHelp;
import com.xbongbong.sys.model.DepartmentModel;
import com.xbongbong.sys.model.UserDepartmentModel;
import com.xbongbong.workflow.domain.entity.WorkflowNodeEntity;
import com.xbongbong.workflow.domain.entity.WorkflowTaskLogEntity;
import com.xbongbong.workflow.domain.entity.WorkflowTaskLogItemEntity;
import com.xbongbong.workflow.model.WorkflowTaskLogItemModel;
import com.xbongbong.workflow.model.WorkflowTaskLogModel;
import com.xbongbong.workflow.pojo.User;
import com.xbongbong.workflow.pojo.WorkflowProcessResultPojo;
import com.xbongbong.workflow.pojo.WorkflowTransferPOJO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 *
 * @author 魏荣杰
 * @date 2021/5/6 16:48
 * @since
 * @version
 */
@Service
@Slf4j
public abstract class AbstractWorkflowNodeStrategy implements WorkflowNodeStrategy{
    @Resource
    private SysUserHelp sysUserHelp;
    @Resource
    private UserDepartmentModel userDepartmentModel;
    @Resource
    private DepartmentModel departmentModel;
    @Resource
    protected WorkflowTaskLogModel workflowTaskLogModel;
    @Resource
    private WorkflowTaskLogItemModel workflowTaskLogItemModel;


    @Override
    public void before(WorkflowTransferPOJO workflowTransferPOJO) {
        WorkflowTaskLogEntity workflowTaskLogEntity = new WorkflowTaskLogEntity();
        workflowTaskLogEntity.setId(workflowTransferPOJO.getLogId());
        workflowTaskLogEntity.setCorpid(workflowTransferPOJO.getCorpid());
        workflowTaskLogEntity.setStatus(WorkflowTaskLogStatusEnum.WAIT.getType());
        workflowTaskLogModel.update(workflowTaskLogEntity);
    }

    @Override
    public WorkflowProcessResultPojo process(WorkflowTransferPOJO workflowTransferPOJO, WorkflowNodeEntity workflowNodeEntity, Long lastNodeId, SaasNeedRedundantAttrPojo saasNeedRedundantAttrPojo) {
        logger(workflowTransferPOJO, workflowNodeEntity, WorkflowTaskLogStatusEnum.PASS, null);
        return new WorkflowProcessResultPojo(true, false);
    }

    @Override
    public void after(WorkflowTransferPOJO workflowTransferPOJO, WorkflowNodeEntity workflowNodeEntity) {
        // 更新logItem的离开时间
        Long logId = workflowTransferPOJO.getLogId();
        String corpid = workflowTransferPOJO.getCorpid();
        WorkflowTaskLogItemEntity workflowTaskLogItemEntity = workflowTaskLogItemModel.getByLogIdNodeIdOrderByAddTime(corpid, logId, workflowNodeEntity.getId());
        long now = DateTimeUtil.getInt();
        if (!Objects.equals(workflowTaskLogItemEntity.getStatus(), WorkflowTaskLogStatusEnum.WAIT.getType())) {
            workflowTaskLogItemEntity.setExitTime(now);
        }
        workflowTaskLogItemEntity.setUpdateTime(now);
        workflowTaskLogItemModel.update(workflowTaskLogItemEntity);
    }

    @Override
    public void check() {

    }

    /**
     * Description: 创建工作流流转节点详细日志
     * @param workflowException
     * @param workflowTransferPOJO
     * @param nodeEntity
     * @param workflowTaskLogStatusEnum
     * @param taskLogId
     * @return void
     * @throws 
     * @author 魏荣杰
     * @date 2021/5/18 16:20
     * @since
     */
    protected void createTaskLogNodeItem(WorkflowTransferPOJO workflowTransferPOJO, WorkflowNodeEntity nodeEntity, WorkflowTaskLogStatusEnum workflowTaskLogStatusEnum, WorkflowException workflowException, Long taskLogId) {
        long now = DateTimeUtil.getInt();
        // 工作流流转日志
        WorkflowTaskLogItemEntity workflowTaskLogItemEntity = new WorkflowTaskLogItemEntity();
        workflowTaskLogItemEntity.setWorkflowTaskLogId(taskLogId);
        workflowTaskLogItemEntity.setCorpid(nodeEntity.getCorpid());
        workflowTaskLogItemEntity.setAppId(nodeEntity.getAppId());
        workflowTaskLogItemEntity.setFormId(nodeEntity.getFormId());
        workflowTaskLogItemEntity.setMenuId(nodeEntity.getMenuId());
        workflowTaskLogItemEntity.setBusinessType(nodeEntity.getBusinessType());
        workflowTaskLogItemEntity.setSaasMark(nodeEntity.getSaasMark());
        workflowTaskLogItemEntity.setWorkflowId(nodeEntity.getWorkflowId());
        workflowTaskLogItemEntity.setTaskId(workflowTransferPOJO.getTaskId() == null ? 0L : workflowTransferPOJO.getTaskId());
        // TODO: 2021/5/13 有特殊逻辑自动通过
        workflowTaskLogItemEntity.setStatus(workflowTaskLogStatusEnum.getType());
        workflowTaskLogItemEntity.setNodeType(nodeEntity.getType());
        // TODO: 2021/5/13 日志内容
        String content = getContent(workflowException);
        workflowTaskLogItemEntity.setContent(content);
        workflowTaskLogItemEntity.setExitTime(0L);
        workflowTaskLogItemEntity.setWorkflowNodeId(nodeEntity.getId());
        workflowTaskLogItemEntity.setAddTime(now);
        workflowTaskLogItemEntity.setUpdateTime(now);
        workflowTaskLogItemEntity.setDel(DelEnum.NORMAL.getDel());

        workflowTaskLogItemModel.insert(workflowTaskLogItemEntity);
    }
    
    @Override
    public void logger(WorkflowTransferPOJO workflowTransferPOJO, WorkflowNodeEntity nodeEntity, WorkflowTaskLogStatusEnum workflowTaskLogStatusEnum, WorkflowException workflowException) {
        WorkflowTaskLogEntity workflowTaskLogEntity = new WorkflowTaskLogEntity();
        workflowTaskLogEntity.setCorpid(workflowTransferPOJO.getCorpid());
        workflowTaskLogEntity.setId(workflowTransferPOJO.getLogId());
        workflowTaskLogEntity.setStatus(workflowTaskLogStatusEnum.getType());
        if (Objects.equals(workflowTaskLogStatusEnum, WorkflowTaskLogStatusEnum.FAIL) || Objects.equals(workflowTaskLogStatusEnum, WorkflowTaskLogStatusEnum.SUSPEND)) {
            workflowTaskLogEntity.setExitTime(DateTimeUtil.getInt());
        }

        String content = getContent(workflowException);
        workflowTaskLogEntity.setContent(content);
        workflowTaskLogEntity.setTaskId(workflowTransferPOJO.getTaskId() == null ? 0L : workflowTransferPOJO.getTaskId());
        workflowTaskLogModel.update(workflowTaskLogEntity);

        createTaskLogNodeItem(workflowTransferPOJO, nodeEntity, workflowTaskLogStatusEnum, workflowException, workflowTaskLogEntity.getId());
    }

    /**
     * 日志内容截取
     * @param workflowException
     * @return
     */
    private String getContent(WorkflowException workflowException) {
        String content = "";
        if (Objects.nonNull(workflowException)) {
            content = workflowException.getMsg();
            if (content != null && content.length() > 500) {
                content = content.substring(0, 500);
            }
        }
        return content;
    }
    
    /**
     * Description: 获取审批节点人员
     * @param optionalRangeEntityList
     * @param workflowTransferPOJO
     * @return void
     * @throws
     * @author 魏荣杰
     * @date 2021/5/18 10:57
     * @since
     */
    protected Set<String> getNodeTaskUserList(List<OptionalRangeEntity> optionalRangeEntityList, WorkflowTransferPOJO workflowTransferPOJO) {
        // 最后需要新建的节点人员id
        Set<String> userIds = new HashSet<>();
        Map<String, List<String>> dynamicLevelMap = new HashMap<>();
        Map<String, List<String>> dynamicUserMap = new HashMap<>();
        Set<String> dynamicUsers = new HashSet<>();
        List<String> roles = new ArrayList<>();
        List<String> departmentList = new ArrayList<>();
        JSONObject data = workflowTransferPOJO.getData().getData();

        for (OptionalRangeEntity optionalRangeEntity : optionalRangeEntityList) {
            if (Objects.equals(optionalRangeEntity.getProperty(), OptionalRangeEnum.DYNAMIC_MANAGER.getValue())) {
                // TODO: 2021/5/17 data内数据格式
                String attr = optionalRangeEntity.getAttr();
                if (Objects.equals(attr, FieldTypeEnum.CREATORID.getAlias())) {
                    User user = workflowTransferPOJO.getUser();
                    dynamicUserMap.computeIfAbsent(attr, v -> new ArrayList<>()).add(user.getUserId());
                    dynamicUsers.add(user.getUserId());
                } else {
                    Object obj = data.get(attr);
                    if (Objects.nonNull(obj)) {
                        if (obj instanceof List) {
                            dynamicUserMap.computeIfAbsent(attr, v -> new ArrayList<>()).addAll((Collection<? extends String>) obj);
                            dynamicUsers.addAll((Collection<? extends String>) obj);
                        } else {
                            dynamicUserMap.computeIfAbsent(attr, v -> new ArrayList<>()).add(obj.toString());
                            dynamicUsers.add(obj.toString());
                        }
                    }
                }
                dynamicLevelMap.computeIfAbsent(attr, v -> new ArrayList<>()).add(optionalRangeEntity.getId());
            } else if (Objects.equals(optionalRangeEntity.getProperty(), OptionalRangeEnum.USER.getValue())) {
                userIds.add(optionalRangeEntity.getId());
            } else if (Objects.equals(optionalRangeEntity.getProperty(), OptionalRangeEnum.ROLE.getValue())) {
                roles.add(optionalRangeEntity.getId());
            } else if (Objects.equals(optionalRangeEntity.getProperty(), OptionalRangeEnum.DEPT.getValue())) {
                departmentList.add(optionalRangeEntity.getId());
            }
        }


        // 动态人员处理
        if (!dynamicUsers.isEmpty()) {

            List<DepartmentEntity> allDepartment = new ArrayList<>();
            try {
                allDepartment = departmentModel.findAllDepartment(workflowTransferPOJO.getCorpid(), true);
            } catch (Exception e) {
                log.error("AbstractWorkflowNodeStrategy.getNodeTaskUserList.error：", e);
            }
            // 所有部门的id和部门的map
            Map<Long, DepartmentEntity> departMap = new HashMap<>();
            if (Objects.nonNull(allDepartment)) {
                allDepartment.forEach(v -> departMap.put(v.getId(), v));
            }
            // 顶级主管
            DepartmentEntity topDepart = departMap.get(1L);
            List<String> topUserIds = userDepartmentModel.getDepManagerList(topDepart);
            Map<String, List<UserDepartmentEntity>> userDepartMap = sysUserHelp.getUserDepartmentMap(workflowTransferPOJO.getCorpid(), dynamicUsers);

            Set<Long> deptList = new HashSet<>();
            for (Map.Entry<String, List<String>> entry : dynamicUserMap.entrySet()) {
                String key = entry.getKey();
                List<String> users = entry.getValue();
                List<String> levels = dynamicLevelMap.get(key);

                for (String userId : users) {
                    List<UserDepartmentEntity> userDepartmentEntities = userDepartMap.getOrDefault(userId, new ArrayList<>());
                    sysUserHelp.getUserIdAndDepartmentId(userDepartmentEntities, departMap, levels, userIds, userId, topUserIds, deptList);
                }
            }

            userIds.addAll(sysUserHelp.getUserIdIsLeader(workflowTransferPOJO.getCorpid(), deptList));
        }

        // 去除离职人员
        Set<String> userIdList = sysUserHelp.getUserIdList(workflowTransferPOJO.getCorpid(), userIds);

        // role的处理
        userIdList.addAll(sysUserHelp.getUserIdListByRole(workflowTransferPOJO.getCorpid(), roles));

        // department的处理
        userIdList.addAll(sysUserHelp.getUserIdListByDepartment(workflowTransferPOJO.getCorpid(), departmentList));
        return userIdList;
    }




    /**
     * 判断是否可以更新
     * @param formDataList
     * @param type
     * @return
     */
    protected boolean isTrue(Set<Long> formDataList, Integer type) {
        // 删除和更新需要控制在50条以内；
        // 更新和新建可以为空，但是需要在50条以内
        if (Objects.isNull(formDataList)) {
            return false;
        }
        if (Objects.equals(RuleOperationEnum.UPDATE_AND_INSERT.getType(), type)) {
            return formDataList.size() <= PaasConstant.LIMIT_MAX_NUM;
        } else if (!Objects.equals(RuleOperationEnum.UPDATE_AND_INSERT.getType(), type)) {
            return CollectionsUtil.isNotEmpty(formDataList) && formDataList.size() <= PaasConstant.LIMIT_MAX_NUM;
        }
        return false;
    }

}
